﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using System.Threading;
using eLib;

namespace frmBG
{
    /// <summary>
    /// виды функции, которая передается в bg процесс
    /// </summary>
    /// <param name="args"></param>
    /// <param name="worker"></param>
    /// <param name="e"></param>
    /// <returns></returns>
    public delegate void Worksheet_ProcessProcedure(Dictionary<string,object> args, 
        Worksheet ws, //target
        BackgroundWorkerEx.BackgroundWorkerEx worker, DoWorkEventArgs e);
    public delegate void ProcessProcedure(Dictionary<string, object> args,
        object target, 
        BackgroundWorkerEx.BackgroundWorkerEx worker, DoWorkEventArgs e);


    public partial class frmBG : Form
    {
        public frmBG()
        {
            InitializeComponent();
        }


        public static bool ProcessWorkSheet(string caption,
            Worksheet_ProcessProcedure pProcedure,
            Dictionary<string, object> Args,
            Worksheet ws)
        {
            frmBG f = new frmBG();
            f.Text = caption;
            f.progressBar.Value = 0;
            f.proc = pProcedure;
            f.args.Clear();
            if (Args != null)
                foreach (KeyValuePair<string, object> kp in Args)
                    f.args.Add(kp.Key, kp.Value);
            f.bgWe.Tag = ws;
            f.bgWe.DoWork += new DoWorkEventHandler(f.bgWe_DoWork);
            bool res = f.ShowDialog() == DialogResult.OK;
            if (res) ws = (Worksheet)f.bgWe.Tag;
            return res;
        }

        public static bool Process(string caption,
            ProcessProcedure pProcedure,
            Dictionary<string, object> Args,
            object target)
        {
            frmBG f = new frmBG();
            f.Text = caption;
            f.progressBar.Value = 0;
            f.procT = pProcedure;
            f.args.Clear();
            if (Args != null)
                foreach (KeyValuePair<string, object> kp in Args)
                    f.args.Add(kp.Key, kp.Value);
            f.bgWe.Tag = target;
            f.bgWe.DoWork += new DoWorkEventHandler(f.bgWe_DoWorkT);
            bool res = f.ShowDialog() == DialogResult.OK;
            if (res) target = f.bgWe.Tag;
            return res;
        }

        Worksheet_ProcessProcedure proc;
        ProcessProcedure procT;
        Dictionary<string, object> args = new Dictionary<string,object>();

        private void bgWe_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorkerEx.BackgroundWorkerEx worker =
                sender as BackgroundWorkerEx.BackgroundWorkerEx;
            proc((Dictionary<string, object>)e.Argument, (Worksheet)worker.Tag, worker, e);
        }

        private void bgWe_DoWorkT(object sender, DoWorkEventArgs e)
        {
            BackgroundWorkerEx.BackgroundWorkerEx worker =
                sender as BackgroundWorkerEx.BackgroundWorkerEx;
            procT((Dictionary<string, object>)e.Argument, worker.Tag, worker, e);
        }

        private void bgWe_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message, "Ошибка при выполнении операции");
                DialogResult = DialogResult.Abort;
            }
            else if (e.Cancelled)
            {
                DialogResult = DialogResult.Cancel;
            }
            else
            {
                (sender as BackgroundWorkerEx.BackgroundWorkerEx).Tag = e.Result;
                DialogResult = DialogResult.OK;
            }
        }

        private void bgWe_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar.Value = e.ProgressPercentage;
        }

        private void bgWe_OnCaptionChanged(BackgroundWorkerEx.BackgroundWorkerEx sender)
        {
            //lbl.Text = sender.StepCaption;
            SetText(sender.StepCaption);
        }

        private void frmBG_Shown(object sender, EventArgs e)
        {
            bgWe.RunWorkerAsync(args);
        }

        private void bCancel_Click(object sender, EventArgs e)
        {
            bgWe.CancelAsync();
        }


        // This delegate enables asynchronous calls for setting
        // the text property on a TextBox control.
        delegate void SetTextCallback(string text);

        private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.lbl.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.lbl.Text = text;
            }
        }

    }
}